home *** CD-ROM | disk | FTP | other *** search
/ Amiga Aktuell / Amiga Aktuell.iso / amiga-aktuell / net tools / fido net / statty / statty.rexx < prev    next >
OS/2 REXX Batch file  |  1996-09-05  |  25KB  |  839 lines

  1. /*
  2. ** $VER: statty.rexx 3.0 (3.7.96) Rolf Rotvel
  3. **
  4. ** Uses rexxtricks.library, locale.library and rexxlocaldates.library
  5. */ 
  6.  
  7. area.mmtaglen = 30              /* In MM log tagnames are cut off after x chars */
  8. path.cfg = 'mail:statty.cfg'    /* Default path to cfg file */
  9.  
  10. /*
  11. ** Initializing
  12. */
  13.  
  14. signal on syntax
  15. signal on error
  16.  
  17. /* Load libraries */
  18. call addlib('rexxsupport.library', 0, -30, 0)
  19. call addlib('rexxtricks.library', 0, -30, 0)
  20. call addlib('locale.library', 0, -30, 0)
  21. call addlib('rexxlocaldates.library', 0, -30, 0)
  22.  
  23. /* Parse argument - if any */
  24. if arg() > 0 then do
  25.     parse arg path.cfg
  26.     if path.cfg = '?' then do 
  27.         options prompt 'CONFIGFILE: '
  28.         parse pull path.cfg
  29.         if path.cfg = '' then exit
  30.     end
  31. end
  32.  
  33. /* Get localized error strings */
  34. cat = opencatalog('statty.catalog', 'english',)
  35. msg.err_cfg = getcatalogstr(cat, 1, "Couldn't read configfile:")
  36. msg.err_tosser = getcatalogstr(cat, 2, "Statty doesn't support:")
  37. call closecatalog(cat)
  38.  
  39. /* Read & parse cfg file */
  40. if ~readfile(path.cfg, cfg) then call errorexit(msg.err_cfg||' "'||path.cfg||'"')
  41. do c = 1 to cfg.0
  42.     interpret cfg.c
  43. end
  44. drop cfg.
  45.  
  46. /* Check tosser */
  47. uptosser = upper(tosser)
  48. select
  49.     when uptosser = 'FOOZLE' then nop
  50.     when uptosser = 'SPOT' then nop
  51.     when uptosser = 'MAILMANAGER' then nop
  52.     otherwise call errorexit(msg.err_tosser||' "'||tosser||'"')
  53. end
  54.  
  55. /* Get rest of error strings */
  56. cat = opencatalog('statty.catalog', 'english',)
  57. msg.err_read = getcatalogstr(cat, 3, "Couldn't read")
  58. msg.err_find = getcatalogstr(cat, 4, "Couldn't find")
  59. msg.err_del = getcatalogstr(cat, 5, "Couldn't delete")
  60. msg.err_create = getcatalogstr(cat, 6, "Couldn't create")
  61. msg.err_write = getcatalogstr(cat, 7, "Couldn't write")
  62.  
  63. /* Message strings */
  64. if keeplog? then msg.bak_log = getcatalogstr(cat, 20, 'Backing up log to')
  65.  
  66. msg.no_msgs = getcatalogstr(cat, 21, 'No new messages to process')
  67. msg.read = getcatalogstr(cat, 22, 'Reading')
  68. msg.fin = getcatalogstr(cat, 23, 'Finished')
  69. msg.calcdb = getcatalogstr(cat, 26, 'Calculating database')
  70. msg.write = getcatalogstr(cat, 27, 'Writing')
  71.  
  72. if tosser = 'MailManager' then msg.dup_area = getcatalogstr(cat, 25, 'added to')
  73. else do
  74.     msg.dup_area = getcatalogstr(cat, 24, 'Found areaname "%s" twice in')
  75.     if tosser = 'Spot' then do
  76.         msg.xport_start = getcatalogstr(cat, 28, 'Export started')
  77.         msg.xport_end = getcatalogstr(cat, 29, 'Export ended')
  78.     end
  79. end
  80.  
  81. /* Strings used in outputfile */
  82. msg.out_1 = getcatalogstr(cat, 100, 'echomail database created by Statty')
  83. msg.out_2 = getcatalogstr(cat, 101, 'Database was started:')
  84. msg.out_3 = getcatalogstr(cat, 102, 'Messages in database:')
  85. msg.out_4 = getcatalogstr(cat, 103, 'to you')
  86. msg.out_5 = getcatalogstr(cat, 104, 'from you')
  87. msg.out_6 = getcatalogstr(cat, 105, 'This update')
  88. msg.out_7 = getcatalogstr(cat, 106, 'Last update')
  89. msg.out_8 = getcatalogstr(cat, 107, 'new messages')
  90. msg.out_9 = getcatalogstr(cat, 108, 'in %s areas')
  91. msg.out_10 = getcatalogstr(cat, 109, 'Areas')
  92. msg.out_11 = getcatalogstr(cat, 110, 'Total')
  93. msg.out_12 = getcatalogstr(cat, 111, 'New')
  94. call closecatalog(cat)
  95.  
  96. /* Check paths */
  97. if ~exists(path.log) then call errorexit(msg.err_find||' '||path.log)
  98. if ~exists(path.area) then call errorexit(msg.err_find||' '||path.area)
  99.  
  100. /*
  101. ** Main
  102. */
  103.  
  104. /* Datestamp */ 
  105. start.thisdb = date('i')||'.'||time('s')
  106.  
  107. /* Multitasking... */
  108. call pragma('p', -1)
  109.  
  110. /* Backup logfile */
  111. if keeplog? then do
  112.     if path.keeplog ~= '' then oldpath = makepath(pathpart(path.log), path.keeplog)
  113.     else oldpath = path.log||'.statty'
  114.  
  115.     say msg.bak_log||' '||oldpath
  116.  
  117.     if exists(oldpath) then call copyfile(path.log, oldpath, 'a')
  118.     else call copyfile(path.log, oldpath, 'c')
  119. end
  120.  
  121. /* Read excludefile */
  122. if path.exc = '' then path.exc = makepath(pathpart(path.db), 'statty.exclude')
  123. if ~readfile(path.exc, area.exc) then area.exc.0 = 0
  124.  
  125. /* Parse db and area files */
  126. if exists(path.db) then do
  127.     say msg.read||' '||path.db
  128.     if ~readfile(path.db, line) then call errorexit(msg.err_read||' '||path.db)
  129.     parse var line.1 start.firstdb start.lastdb start.areastamp .
  130.  
  131.     parse value statef(path.area) with . . . . days mins ticks .
  132.     chkstamp = days||mins||ticks
  133.  
  134.     if start.areastamp ~= chkstamp then do
  135.         start.areastamp = chkstamp
  136.  
  137.         interpret 'call '||tosser||'area()'
  138.  
  139.         num = 1
  140.         do d = 2 to line.0
  141.             parse var line.d _msgs '"' _name '"' _toyou _fromyou  .
  142.             db.name.num = _name
  143.             db.msgs.num = _msgs
  144.             db.toyou.num = _toyou
  145.             db.fromyou.num = _fromyou
  146.             say count(num)
  147.             num = num + 1
  148.         end
  149.         db.name.0 = num - 1
  150.  
  151.     end
  152.     else do 
  153.         num = 1
  154.         do d = 2 to line.0
  155.             parse var line.d _msgs '"' _name '"' _toyou _fromyou  .
  156.  
  157.             if area.exc.0 > 0 then do
  158.                 if lsearch(_name, area.exc) ~= -1 then iterate
  159.             end
  160.             
  161.             area.name.num = _name
  162.             db.name.num = _name
  163.             db.msgs.num = _msgs
  164.             db.toyou.num = _toyou
  165.             db.fromyou.num = _fromyou
  166.             say count(num)
  167.             num = num + 1
  168.         end
  169.         area.name.0 = num - 1
  170.         db.name.0 = area.name.0
  171.     end
  172. end
  173. else do
  174.     interpret 'call '||tosser||'area()'
  175.  
  176.     start.firstdb = start.thisdb
  177.     start.lastdb = start.thisdb
  178.  
  179.     parse value statef(path.area) with . . . . days mins ticks .
  180.     start.areastamp = days||mins||ticks
  181.  
  182.     do a = 1 to area.name.0
  183.         db.name.a = area.name.a
  184.         db.msgs.a = 0 
  185.         db.toyou.a = 0
  186.         db.fromyou.a = 0
  187.     end
  188. end
  189.  
  190. /* Parse log file */
  191. log.name.0 = 0
  192. interpret 'call '||tosser||'log()'
  193. if log.name.0 = 0 then say msg.no_msgs
  194. else do
  195.     call calculatedb()    /* Calculate database */
  196.     call putdb()          /* Write database */
  197.     call genoutput()      /* Write output */
  198. end
  199. if ~delete(path.log) then call errorexit(msg.err_del||' '||path.log)
  200. say msg.fin
  201. exit
  202.  
  203.  
  204. ERROREXIT: 
  205. say arg(1) 
  206. exit 10
  207.  
  208.  
  209. SPOTAREA: procedure expose area. msg. path.
  210. say msg.read||' '||path.area
  211. if ~readfile(path.area, line) then call errorexit(msg.err_read||' '||path.area)
  212.  
  213. num = 1
  214.  
  215. do a = 1 to line.0
  216.     chk = upper(line.a)
  217.  
  218.     /* Skip separator, bad, default & netmail areas */
  219.     if pos(' SEPARATOR', chk) > 0 | pos(' BAD', chk) > 0 |,
  220.        pos(' DEFAULT', chk) > 0 | pos(' NETMAIL', chk) > 0 then iterate
  221.     parse var line.a . '"' . '"' '"' _user '"'
  222.  
  223.     /* Is areaname in excludefile? */
  224.     if area.exc.0 > 0 then do
  225.         if lsearch(_user, area.exc) ~= -1 then iterate
  226.     end
  227.  
  228.     /* A duplicate (user) areaname?!? */
  229.     if lsearch(_user, area.name) ~= -1 then call errorexit,
  230.         (replace(msg.dup_area, '%s', _user)||' '||path.area||'!')
  231.  
  232.     area.name.num = _user
  233.     area.name.0 = num       /* Needed for lsearch() */                    
  234.     say count(num)
  235.     num = num + 1
  236.  
  237. end
  238. return
  239.  
  240.  
  241. FOOZLEAREA: procedure expose area. msg. path.
  242. say msg.read||' '||path.area
  243. if ~open('tmp', path.area, 'r') then call errorexit(msg.err_read||' '||path.area)
  244.  
  245. num = 1
  246. null = '0'x
  247.  
  248. do forever
  249.     _name = readch('tmp', 24)                           /* Read areaname */
  250.     if eof('tmp') then leave                            /* Break condition */
  251.     tag = upper(strip(readch('tmp', 24), 't', null))    /* Read tagname */
  252.     dir = compress(readch('tmp', 32), null)             /* Read areadir */
  253.     call seek('tmp', 128 + 520)                         /* Skip rest of area definition */
  254.                                                         /* Iterate if not valid area ? */
  255.     if dir = '' | ~exists(dir) | tag = 'BAD' |,     
  256.        tag = 'MATRIX' then iterate
  257.  
  258.     _name = strip(_name, 't', null)
  259.  
  260.     /* Is areaname in excludefile? */
  261.     if area.exc.0 > 0 then do
  262.         if lsearch(_name, area.exc) ~= -1 then iterate
  263.     end
  264.  
  265.                                                         /* A duplicate areaname?!? */
  266.     if lsearch(_name, area.name) ~= -1 then call errorexit,
  267.         (replace(msg.dup_area, '%s', _name)||' '||path.area||'!')
  268.  
  269.  
  270.     area.name.num = _name
  271.     area.name.0 = num                                   /* Needed for lsearch() */
  272.     say count(num)
  273.     num = num + 1
  274. end
  275.  
  276. call close('tmp')
  277. return
  278.  
  279.  
  280. MAILMANAGERAREA: procedure expose area. msg. path.
  281. say msg.read||' '||path.area
  282. if ~readfile(path.area, line) then call errorexit(msg.err_read||' '||path.area)
  283.  
  284. num = 1
  285. start = 1
  286.  
  287. do forever
  288.     /* Skip bad, netmail, fileecho & tick areas */
  289.     a = lsearch("'#ECHOAREA #?", line, start,, pattern)
  290.     if a = -1 then leave            
  291.     start = a + 1
  292.  
  293.     parse var line.a . '"' . '"' _name .
  294.  
  295.     /* Is areaname in excludefile? */
  296.     if area.exc.0 > 0 then do
  297.         if lsearch(_name, area.exc) ~= -1 then iterate
  298.     end
  299.  
  300.     if length(_name) > area.mmtaglen then do
  301.         subname = left(_name, area.mmtaglen)
  302.         chk = lsearch(subname||'#?', area.name,,, 'p') 
  303.         if chk ~= -1 then do         
  304.             say '"'||_name||'" '||msg.dup_area||' '||path.exc
  305.             if area.exc.0 > 0 then call open('tmp', path.exc, 'a') 
  306.             else do
  307.                 if ~open('tmp', path.exc, 'w') then call errorexit(msg.err_create||' '||path.exc)
  308.                 area.exc.0 = 1
  309.             end
  310.             call writeln('tmp', _name)
  311.             call close('tmp')
  312.         end
  313.     end
  314.  
  315.     area.name.num = _name
  316.     area.name.0 = num
  317.     say count(num)
  318.     num = num + 1
  319. end
  320. return
  321.  
  322.  
  323. SPOTLOG: procedure expose log. area. msg. path.
  324. say msg.read||' '||path.log
  325. if ~readfile(path.log, line) then call errorexit(msg.err_read||' '||path.log)
  326.  
  327. num = 1
  328. export? = 0
  329.  
  330. do l = 1 to line.0
  331.     first = left(line.l, 1)
  332.     select
  333.         when pos(msg.xport_start, line.l) > 0 then export? = 1
  334.         when pos(msg.xport_end, line.l) > 0 then export? = 0
  335.         when first = '*' | first = '!' then do
  336.             parse var line.l . "'" _name "'" rest
  337.  
  338.             /* Iterate if it's not a valid areaname */
  339.             if lsearch(_name, area.name) = -1 then iterate
  340.             
  341.             /* Find amount of msgs imported */
  342.             wds = words(rest)
  343.             do w = 1 to wds
  344.                 _msgs = word(rest, w)
  345.                 if datatype(_msgs, 'w') then leave
  346.             end
  347.  
  348.             /* Parse rest of line if any msgs for you */
  349.             if ~export? then do
  350.                 if first = '*' then do ww = w + 1 to wds
  351.                     _toyou = word(rest, ww)
  352.                     if datatype(_toyou, 'w') then leave
  353.                 end
  354.                 else _toyou = 0
  355.  
  356.                 /* Is it first time we find this areaname in logfile? */
  357.                 chk = lsearch(_name, log.name)
  358.                 if chk = -1 then do         /* Initialize variables */
  359.                     log.name.num = _name
  360.                     log.msgs.num = _msgs
  361.                     log.toyou.num = _toyou
  362.                     log.fromyou.num = 0
  363.                     log.name.0 = num        /* Need this for lsearch() */
  364.                     say count(num)
  365.                     num = num + 1
  366.                 end
  367.                 else do                     /* Update variables */
  368.                     log.msgs.chk = log.msgs.chk + _msgs
  369.                     log.toyou.chk = log.toyou.chk + _toyou
  370.                 end
  371.             end
  372.             else do /* Export! */
  373.                 chk = lsearch(_name, log.name)
  374.                 if chk = -1 then do         /* Initialize variables */
  375.                     log.name.num = _name
  376.                     log.msgs.num = _msgs
  377.                     log.toyou.num = 0
  378.                     log.fromyou.num = _msgs
  379.                     log.name.0 = num        /* Need this for lsearch() */
  380.                     say count(num)
  381.                     num = num + 1
  382.                 end
  383.                 else do                     /* Update variables */
  384.                     log.msgs.chk = log.msgs.chk + _msgs
  385.                     log.fromyou.chk = log.fromyou.chk + _msgs
  386.                 end
  387.             end
  388.         end
  389.         otherwise nop
  390.     end
  391. end
  392. return
  393.  
  394.  
  395. FOOZLELOG: procedure expose log. area. path. msg.
  396. say msg.read||' '||path.log
  397. if ~readfile(path.log, line) then call errorexit(msg.err_read||' '||path.log)
  398.  
  399. num = 1
  400.  
  401. do l = 1 to line.0
  402.     if word(line.l, 4) = 'Area' then do
  403.         parse var line.l . '"' _name '"' rest
  404.         /* Iterate if it's not a valid areaname */
  405.         if lsearch(_name, area.name) = -1 then iterate
  406.         /* Find amount of msgs imported */
  407.         wds = words(rest)
  408.         do w = 1 to wds
  409.             _msgs = word(rest, w)
  410.             if datatype(_msgs, 'w') then leave
  411.         end
  412.  
  413.         /* Parse rest of line if any msgs for you */
  414.         if right(line.l, 7) = 'for you' then do ww = w + 1 to wds
  415.             _toyou = word(rest, ww)
  416.             if datatype(_toyou, 'w') then leave
  417.         end
  418.         else _toyou = 0
  419.  
  420.         /* Is it first time we find this areaname in logfile? */
  421.         chk = lsearch(_name, log.name)
  422.         if chk = -1 then do         /* Initialize variables */
  423.             log.name.num = _name
  424.             log.msgs.num = _msgs
  425.             log.toyou.num = _toyou
  426.             log.fromyou.num = 0     /* Foozle doesn't support this...*/
  427.             log.name.0 = num        /* Need this for lsearch() */
  428.             say count(num)
  429.             num = num + 1
  430.         end
  431.         else do                     /* Update variables */
  432.             log.msgs.chk = log.msgs.chk + _msgs
  433.             log.toyou.chk = log.toyou.chk + _toyou
  434.         end
  435.     end
  436. end
  437. return
  438.  
  439.  
  440. MAILMANAGERLOG: procedure expose log. area. msg. path.
  441. say msg.read||' '||path.log
  442. if ~readfile(path.log, line) then call errorexit(msg.err_read||' '||path.log)
  443.  
  444. num = 1
  445.  
  446. startimp = 'Import Statistics'
  447. endimp   = 'Import Used'
  448.  
  449. startexp = 'Start Export Function'
  450. endexp   = 'End Export Function'
  451.  
  452. action = ''
  453.  
  454. do l = 1 to line.0
  455.     if action = '' then do
  456.         select
  457.             when pos(startimp, line.l) > 0 then action = 'imp'
  458.             when pos(startexp, line.l) > 0 then action = 'exp'
  459.             otherwise nop
  460.         end
  461.     end
  462.     else do
  463.         select
  464.             when pos(endimp, line.l) > 0 then action = ''
  465.             when pos(endexp, line.l) > 0 then action = ''
  466.             when word(line.l, 7) = 'Area' then do
  467.                 if action = 'imp' then do
  468.                     parse var line.l . 'Area' _name _msgs '(' _toyou ')'
  469.  
  470.                     /* Iterate if it's not a valid areaname */
  471.                     if length(_name) < area.mmtaglen then chk = lsearch(_name, area.name)
  472.                     else chk = lsearch(_name||'#?', area.name,,, 'p')
  473.                     if chk = -1 then iterate
  474.  
  475.                     _msgs = strip(_msgs)
  476.                     _toyou = strip(_toyou)
  477.  
  478.                     /* Is it first time we find this areaname in logfile? */
  479.                     chk = lsearch(_name, log.name)
  480.                     if chk = -1 then do         /* Initialize variables */
  481.                         log.name.num = _name
  482.                         log.msgs.num = _msgs
  483.                         log.toyou.num = _toyou
  484.                         log.fromyou.num = 0
  485.                         log.name.0 = num        /* Need this for lsearch() */
  486.                         say count(num)
  487.                         num = num + 1
  488.                     end
  489.                     else do                     /* Update variables */
  490.                         log.msgs.chk = log.msgs.chk + _msgs
  491.                         log.toyou.chk = log.toyou.chk + _toyou
  492.                     end
  493.                 end
  494.                 else do     /* Standalone export */
  495.                     parse var line.l . 'Area' _name _fromyou .
  496.  
  497.                     if length(_name) < area.mmtaglen then chk = lsearch(_name, area.name)
  498.                     else chk = lsearch(_name||'#?', area.name,,, 'p')
  499.                     if chk = -1 then iterate
  500.     
  501.                     chk = lsearch(_name, log.name)
  502.                     if chk = -1 then do         /* Initialize variables */
  503.                         log.name.num = _name
  504.                         log.msgs.num = _fromyou
  505.                         log.toyou.num = 0
  506.                         log.fromyou.num = _fromyou
  507.                         log.name.0 = num        /* Need this for lsearch() */
  508.                         say count(num)
  509.                         num = num + 1
  510.                     end
  511.                     else do                     /* Update variables */
  512.                         log.msgs.chk = log.msgs.chk + _fromyou
  513.                         log.fromyou.chk = log.fromyou.chk + _fromyou
  514.                     end
  515.                 end
  516.             end
  517.             otherwise nop
  518.         end
  519.     end
  520. end
  521. return
  522.  
  523.  
  524. CALCULATEDB: procedure expose area. msg. log. db.
  525. say msg.calcdb
  526.  
  527. area.length = 0
  528.  
  529. area.maxmsgs = 0
  530. area.maxtoyou = 0
  531. area.maxnewmsgs = 0
  532. area.maxnewtoyou = 0
  533. area.maxfromyou = 0
  534. area.maxnewfromyou = 0
  535.  
  536. area.totalmsgs = 0
  537. area.totaltoyou = 0
  538. area.totalfromyou = 0
  539.  
  540. area.totallogmsgs = 0
  541. area.totallogtoyou = 0
  542. area.totallogfromyou = 0
  543.  
  544. do a = 1 to area.name.0
  545.     say count(a)
  546.  
  547.     chklog = lsearch(area.name.a, log.name)
  548.     if chklog = -1 then do 
  549.         newmsgs = 0
  550.         newtoyou = 0
  551.         newfromyou = 0
  552.     end
  553.     else do
  554.         newmsgs = log.msgs.chklog
  555.         newtoyou = log.toyou.chklog
  556.         newfromyou = log.fromyou.chklog
  557.     end
  558.  
  559.     chkdb = lsearch(area.name.a, db.name)
  560.     if chkdb = -1 then do 
  561.         dbmsgs = 0
  562.         dbtoyou = 0
  563.         dbfromyou = 0
  564.     end
  565.     else do
  566.         dbmsgs = db.msgs.chkdb
  567.         dbtoyou = db.toyou.chkdb
  568.         dbfromyou = db.fromyou.chkdb
  569.     end
  570.  
  571.     _msgs = newmsgs + dbmsgs
  572.     _toyou = newtoyou + dbtoyou
  573.     _fromyou = newfromyou + dbfromyou
  574.  
  575.     area.totallogmsgs = area.totallogmsgs + newmsgs
  576.     area.totallogtoyou = area.totallogtoyou + newtoyou
  577.     area.totallogfromyou = area.totallogfromyou + newfromyou
  578.  
  579.     area.totalmsgs = area.totalmsgs + _msgs
  580.     area.totaltoyou = area.totaltoyou + _toyou
  581.     area.totalfromyou = area.totalfromyou + _fromyou
  582.  
  583.     area.length = max(area.length, length(area.name.a))
  584.  
  585.     db.string.a = _msgs||' "'||area.name.a||'" '||_toyou||' '||_fromyou
  586.     area.string.a = db.string.a||' '||newmsgs||' '||newtoyou||' '||newfromyou
  587.  
  588.     /* These variables needed when calculating/formatting output */
  589.     area.maxmsgs = max(_msgs, area.maxmsgs)
  590.     area.maxtoyou = max(_toyou, area.maxtoyou)
  591.     area.maxfromyou = max(_fromyou, area.maxfromyou)
  592.  
  593.     area.maxnewmsgs = max(newmsgs +  newtoyou, area.maxnewmsgs)
  594.     area.maxnewtoyou = max(newtoyou, area.maxnewtoyou)
  595.     area.maxnewfromyou = max(newfromyou, area.maxnewfromyou)
  596.  
  597. end
  598. db.string.0 = area.name.0
  599. area.string.0 = area.name.0
  600.  
  601. drop log.
  602. return
  603.  
  604.  
  605. PUTDB: procedure expose db. start. msg. path.
  606. say msg.write||' '||path.db
  607.  
  608. line = start.firstdb||' '||start.thisdb||' '||start.areastamp
  609. call steminsert(db.string, 1,, line)
  610.  
  611. if ~writefile(path.db, db.string) then call errorexit(msg.err_write||' '||path.db)
  612.  
  613. drop db.
  614. return 
  615.  
  616.  
  617. GENOUTPUT: procedure expose start. area. msg. path. tosser toyou? allareas?
  618. say msg.write||' '||path.out
  619.  
  620. /* Convert datestamps to normal dates */
  621. template = '%e %B %Y %R'
  622. loc = openlocale()
  623.  
  624. parse var start.thisdb ds.days '.' ds.seconds
  625. start.thisdb = strip(formatdate(loc, ds, template))
  626.  
  627. if start.firstdb ~= start.thisdb then do
  628.     parse var start.firstdb ds.days '.' ds.seconds
  629.     start.firstdb = strip(formatdate(loc, ds, template))
  630.  
  631.     parse var start.lastdb ds.days '.' ds.seconds
  632.     start.lastdb = strip(formatdate(loc, ds, template))
  633. end
  634. else do
  635.     start.firstdb = start.thisdb
  636.     start.lastdb = start.thisdb
  637. end
  638.  
  639. call closelocale(loc)
  640.  
  641. /* Sort areas */
  642. call qsort(area.string,, 'num', 1)
  643.  
  644. if area.totalfromyou > 0 then fromyou? = 1
  645. else fromyou? = 0
  646.  
  647. msg_len = length(area.maxmsgs)       
  648. newmsg_len = length(area.maxnewmsgs)
  649.  
  650. if toyou? then do
  651.     toyou_len = length(area.maxtoyou)
  652.     newtoyou_len = length(area.maxnewtoyou)
  653.     pad_len = msg_len + 1 + 1 + toyou_len + 1 /* A space + '()' */
  654.     if fromyou? then do 
  655.         fromyou_len = length(area.maxfromyou)
  656.         newfromyou_len = length(area.maxnewfromyou)
  657.         pad_len = pad_len + 1 + fromyou_len   /* A space */
  658.     end
  659. end
  660. else pad_len = msg_len
  661.  
  662. totallen = length(msg.out_11) + 1
  663. width = 3
  664. do while width + pad_len < totallen
  665.     width = width + 1
  666. end
  667. spaces = makespaces(width)
  668. spaces_minus_one = makespaces(width - 1)  /* '100%' kludge */
  669.  
  670. line.1  =  tosser||' '||msg.out_1||' '||word(sourceline(2), 4)
  671. line.2  =  ''
  672. line.3  =  msg.out_2||' '||start.firstdb
  673.  
  674. line.4  =  msg.out_3||' '||area.totalmsgs
  675. if toyou? then do
  676.     if fromyou? then line.4 = line.4||' ('||area.totaltoyou||' '||msg.out_4||', '||area.totalfromyou||' '||msg.out_5||')'
  677.     else line.4 = line.4||' ('||area.totaltoyou||' '||msg.out_4||')'
  678. end
  679.  
  680. line.5 = ''
  681.  
  682. line.6  =  msg.out_6||' '||start.thisdb
  683. line.7  =  msg.out_7||' '||start.lastdb
  684.  
  685. line.8  =  area.totallogmsgs||' '||msg.out_8
  686. if toyou? then do
  687.     if fromyou? then line.8 = line.8||' ('||area.totallogtoyou||' '||msg.out_4||', '||area.totallogfromyou||' '||msg.out_5||')'
  688.     else line.8 = line.8||' ('||area.totallogtoyou||' '||msg.out_4||')'
  689. end
  690. line.8  =  line.8||' '||replace(msg.out_9, '%s', area.string.0)
  691.  
  692. line.9 = ''
  693.  
  694. line.10 = left(msg.out_10, area.length)||spaces||left('%', 5)||spaces||,
  695.           left(msg.out_11, pad_len + width)||msg.out_12
  696.  
  697. line.11 = ''
  698.  
  699. num = 12                             /* Number of lines in header + 1 */
  700.  
  701. do q = area.string.0 to 1 by -1
  702.     parse var area.string.q _msgs '"' areaname '"' _toyou _fromyou newmsgs newtoyou newfromyou .
  703.  
  704.     if ~allareas? & _msgs = 0 then leave
  705.     _msgs = strip(_msgs)
  706.  
  707.     if toyou? then do
  708.         if fromyou? then do
  709.             youtotal = ' ('||right(_toyou, toyou_len)||' '||right(_fromyou, fromyou_len)||')'
  710.             younew = ' ('||right(newtoyou, newtoyou_len)||' '||right(newfromyou, newfromyou_len)||')'
  711.         end
  712.         else do    
  713.             youtotal = ' ('||right(_toyou, toyou_len)||')'
  714.             younew = ' ('||right(newtoyou, newtoyou_len)||')'
  715.         end
  716.     end
  717.     else do
  718.         youtotal = ''
  719.         younew = ''
  720.     end
  721.  
  722.     line.num = left(strip(areaname), area.length)||spaces_minus_one||,
  723.                format(((_msgs / area.totalmsgs) * 100), 3, 2)||spaces||,
  724.                right(_msgs, msg_len)||youtotal||spaces||,
  725.                right(newmsgs, newmsg_len)||younew
  726.  
  727.     say count(num)
  728.     num = num + 1
  729. end
  730.  
  731. line.0 = num - 1
  732.  
  733. if ~writefile(path.out, line) then call errorexit(msg.err_write||' '||path.out)
  734. return
  735.  
  736.  
  737. /*
  738. ** Generic procedures
  739. */
  740.  
  741. MAKESPACES: procedure
  742. return copies(' ', arg(1))
  743.  
  744.  
  745. COUNT: procedure
  746. return ' '||arg(1)||'9b'x||'A'
  747.  
  748.  
  749. FORMAT: procedure
  750. arg number, before, after
  751.  
  752. /* Reformats the number to NUMERIC DIGITS setting */
  753. num = number + 0
  754.  
  755. /* Return the reformatted number if other options not specified */
  756. if before = '' & after = '' then return num
  757.  
  758. /* Split the number into fraction and integer */
  759. parse var num integer '.' fraction
  760.  
  761. /* Set defaults for non-spec'd arguments */
  762. if before = '' then before = length(integer)
  763. if after = '' then after = length(fraction)
  764.  
  765. /* [before] argument must be at least as long as integer   */
  766. if before < length(integer) then return '**ERROR**'
  767.  
  768. /* add an appropriate value of .5 to number to round it    */
  769. if after ~= length(fraction) then do
  770.     fraction = trunc(('.'||fraction||'0') + ('.'||copies('0', after)||'5'), after)
  771.     /* Numbers created as text strings are still numbers */
  772.     integer = integer + (fraction % 1)
  773.     fraction = substr(fraction, 3)
  774. end
  775. if fraction >= 0 then return right(integer, before)||'.'||fraction
  776. else return right(integer, before)
  777.  
  778.  
  779. /*  
  780. ** copyfile(sourcefile, destfile) 
  781. */ 
  782. COPYFILE: procedure
  783. parse arg from, to , mode
  784.  
  785. sz = word(statef(from), 2)
  786.  
  787. call open('s', from, 'r')
  788.  
  789. if upper(mode) = 'A' then call open('d', to, 'a')
  790. else call open('d', to, 'w')
  791.  
  792. do (sz % 65535) + 1      
  793.     call writech('d', readch('s', 65535))
  794. end
  795.  
  796. call close('d')
  797. call close('s')
  798. return
  799.  
  800.  
  801. /*
  802. ** Replace(string, old, new)
  803. */
  804. REPLACE: procedure
  805. parse arg src, old, new
  806. str = ''
  807. do while src ~= ''
  808.   chk = pos(old, src)
  809.   parse var src pre (old) src
  810.   str = str||pre
  811.   if chk > 0 then str = str||new
  812. end
  813. return str
  814.  
  815.  
  816. /*
  817. ** Use while developing...
  818. */
  819. SYNTAX:
  820. ERROR:
  821. trace o
  822. err = rc ; line = sigl
  823. if datatype(err, 'n') then do
  824.     errline = 'Error '||err||': '||errortext(err)||'0a'x||'in line '||line
  825.     sayit? = 1
  826.     if show('p', 'rexx_ced') then do
  827.         parse source . . filename .
  828.         options results
  829.         address 'rexx_ced'
  830.         'cedtofront'
  831.         'ow' filename
  832.         'jump to line' line
  833.         'okay1' errline
  834.         sayit? = 0
  835.     end
  836.     else say errline
  837. end
  838. exit
  839.